<?php
namespace hyang;
/*  数据库模式处理类
 *  数据库选择可： 加载配置文件/动态传入/模式自定义
 */
use hyang\Db;
use hyang\Db\Database;
class Model{
    public $type;//数据表类型
    public $table;//数据表
    public $db;//数据对象
    public $pk; //数据表主键
    public $fk; //数据表外键/ string/array> Oracle格式示例 "tbale"."uid"-可自动匹配对应模式，进行关联操作
    public $dbOpt;//数据库连接选项
    public $colList;//  类列表
    public $colDefualt;// 项目默认处理字段赋值-!!私有属性无法继承/无法再继承类中修改-可通过公共方法操作
    public $schemas;// 数据库创建脚本，用于-对简单数据表的创建和删除测试    

    private $tableLink;// 链式数据表动态设置-用于数据表切换处理
    private $whereLink;// 链式数据-条件
    private $fieldLink;// 链式数据-列名
    private $pageLink;// 链式数据-分页
    private $orderLink;// 链式数据-排序
    private $groupLink;// 链式数据-分组
    private $pageBarLink;// 伪链式分页器
    private $dataLink;// 伪链式数据-预设数据
    private $buildLink;// 伪链式数据-创建SQL

    public function __construct($dbOpt=null)
    {
        $this->_init();
        //---------- 默认值处理 ------------------begin》
        if(empty($this->table)) $this->table = strtolower(get_class($this));
        // 空模型处理
        if(!get_parent_class($this)){
            if(is_string($dbOpt) && $dbOpt) $this->table = $dbOpt;
            elseif(isset($dbOpt['table'])){
                $this->table = $dbOpt['table'];
                unset($dbOpt['table']);
                if(count($dbOpt) == 0) $dbOpt = null;
            }
        }
        
        // 数据默认列获取值
        $data = $this->colDft();
        if(is_array($data) && !empty($this->colDefualt)) $this->colDefualt = $data;
        // 设计字段-可根据定义创建数据表
        if(empty($this->colList)) $this->colList = [];// [列名=>' 创建数据选项']
        //---------- 默认值处理 ------------------end》
        if(is_array($dbOpt)) $opt = $dbOpt;
        else $opt = is_array($this->dbOpt)? $this->dbOpt:null;
        $this->dbOpt = $opt;
        $this->db = new Db($opt);
        // 初始化后处理
        $this->_afterInit();
    }
    // 数据初始化-设置数据的属性-数据接口
    public function _init(){}
    public function _afterInit(){}
    // 默认字段参数数据
    public function colDft(){}
    public function init(){}// 模式初始化处理-覆盖 系统默认的_init方法
    // 创建数据表
    public function create($param=null){
        $feekSql = $this->buildLink;$this->buildLink = null;
        $sql = $this->schemas;//sql创建数据库        
        if($sql){
            if($feekSql) return $sql;
            return $this->db->create($sql);
        }
        elseif($param) return $this->db->create($param,$feekSql);
        else{// 构建
            $cols = $this->colList;
            if(is_array($cols)){
                return $this->db->create([
                        'table'=>$this->table,'value'=>$cols
                    ],$feekSql);
            }
        }
        return false;
    }
    // 删除数据表- $param 传入数组来实现对其他对象的删除/ 支持链式 build/table
    public function drop($param=null)
    {
        $feekSql = $this->buildLink;$this->buildLink = null;
        $table = $this->tableLink? $this->tableLink:$this->table;
        $this->tableLink = null;
        if(empty($param)){
            $param = ['table'=>$table];
        }
        if(empty($param)) return false;
        return $this->db->drop($param,$feekSql);
    }
    // 新增数据- 支持 data/table 链式
    public function add($param=null)
    {
        if(is_array($this->dataLink)){$data = $this->dataLink;$this->dataLink = null;}
        if(is_array($param)) $data = $param;
        $dftData = $this->colDefualt;
        if(is_array($dftData)) $data = array_merge($dftData,$data);
        $table = $this->tableLink? $this->tableLink:$this->table;
        $this->tableLink = null;
        if($this->buildLink){$this->buildLink=null;return $this->db->parseInsert($data,$table);}
        return $this->db->add($table,$data);
    }
    // 返回新增数据的ID
    public function getId(){return $this->db->getAddId();}
    // 删除数据- 支持链式 where/table
    public function delete($where=null)
    {
        $wh = $where? $where:$this->whereLink;
        $this->whereLink = null;
        $table = $this->tableLink? $this->tableLink:$this->table;
        $this->tableLink = null;
        return $this->db->delete($table,$wh);
    }
    // 数据更改 支持链式- table/data/where 数据绑定法
    public function update($data=null)
    {
        if(is_array($this->dataLink)){$data = $this->dataLink;$this->dataLink = null;}
        if(empty($data)) return 0;        
        $where = null;
        if($this->whereLink){$where = $this->whereLink;$this->whereLink = null;}
        $isBind = is_array($where)? true:false;
        $table = $this->tableLink? $this->tableLink:$this->table;
        $this->tableLink = null;
        return $this->db->update($table,$data,$where,$isBind);
    }
    // 通过ID查询数据-获取单列数据- 支持链式 table/field
    public function get($pk)
    {
        $key = $this->pk;
        if(empty($key)) return '';
        if(is_array($pk)) $map = $pk;
        else $map = [$key=>$pk];
        $field = $this->fieldLink;
        $table = $this->tableLink? $this->tableLink:$this->table;
        // 链式数据资源释放
        $this->fieldLink = null;$this->tableLink = null;
        return $this->db->selectById($table,$map,$field);
    }
    // 全部查询-支持链式 table/field/where/page/order/group
    public function select($where=null,$bind=null,$havingCount=false)
    {
        $field = $this->fieldLink;
        $wh = $where? $where:$this->whereLink;
        $pg = $this->pageLink;
        $appendSql = '';
        if($this->groupLink){$appendSql = $this->groupLink;$this->groupLink=null;}
        if($this->orderLink){$appendSql = $this->orderLink;$this->orderLink=null;}
        $table = $this->tableLink? $this->tableLink:$this->table;    
        if(is_array($pg)) $tb = [$table,'Pager',$pg];
        else $tb = $table;
        $data = $this->db->select($tb,$wh,$appendSql,$field,$bind);
        if($havingCount){
            $ctt = $this->count();
            $data['count'] = $ctt;
        }
        // 伪链式启动器
        if($this->pageBarLink && $pg){
            $ct = $this->count();$page = $pg['page'];$num = $pg['num'];
            $fpg = floor($ct/$num);
            $data = [
                'src'=>$data,//数据源
                'pageBar'=>[// 分页参数
                    'count' => $ct,
                    'page'  => $page,
                    'num'   => $num,
                    'fPage' => $fpg
                ],
            ];
        }
        //链式数据资源释放
        $this->fieldLink = null;$this->whereLink = null;$this->pageLink = null;$this->tableLink = null;$this->pageBarLink = null;
        return $data;
    }
    // (聚合函数)统计数据条数 -count/sum/avg/max/min;支持链式操作 where
    public function count($colname=null){
        $wh = $this->whereLink;
        $table = $this->tableLink? $this->tableLink:$this->table;
        // 链式释放值
        $this->tableLink = null;$this->whereLink = null;
        return $this->db->aggregate($table,'count',$colname,$wh);
    }
    public function avg($colname=null){        
        $wh = $this->whereLink;
        $table = $this->tableLink? $this->tableLink:$this->table;
        // 链式释放值
        $this->tableLink = null;$this->whereLink = null;
        return $this->db->aggregate($table,'avg',$colname,$wh);
    }
    public function max($colname=null){        
        $wh = $this->whereLink;
        $table = $this->tableLink? $this->tableLink:$this->table;
        // 链式释放值
        $this->tableLink = null;$this->whereLink = null;
        return $this->db->aggregate($table,'max',$colname,$wh);
    }
    public function min($colname=null){        
        $wh = $this->whereLink;
        $table = $this->tableLink? $this->tableLink:$this->table;
        // 链式释放值
        $this->tableLink = null;$this->whereLink = null;
        return $this->db->aggregate($table,'min',$colname,$wh);
    }
    public function sum($colname=null){        
        $wh = $this->whereLink;
        $table = $this->tableLink? $this->tableLink:$this->table;
        // 链式释放值
        $this->tableLink = null;$this->whereLink = null;
        return $this->db->aggregate($table,'sum',$colname,$wh);
    }
     // 数据表是否存在-支持回调
    public function havingTb($tb=null,$fbck=null)
    {
        $tb = $tb? $tb:$this->table;
        if($this->tableLink){$tb = $this->tableLink;$this->tableLink=null;}
        $ret = $this->db->table_exist($tb);
        if(is_callable($fbck)) return $fbck($ret,$this);
        return $ret; 
    }
    /********************** 数据库附加处理 *************************/
    // 获取当前-数据库信息
    public function dbInfo()
    {
        $dbInfo = new Database([
            'option'=>$this->getOpt(),'db'=>$this->db,'model'=>$this
        ]);
        return $dbInfo;
    }
    public function getOpt(){
        $opt = $this->dbOpt;
        if(empty($opt)){
            $this->dbOpt = $this->db->option;
            $opt = $this->dbOpt;
        }
        return $opt;
    }
    // 返回当前执行的sql
    public function _sql(){return $this->db->_sql();}
    public function _error(){return $this->db->_error();} 
    public function fetchRow($sql,$bind=null){return $this->db->fetchRow($sql,$bind);}
    public function fetchOne($sql,$bind=null){return $this->db->fetchOne($sql,$bind);}
    public function query($sql,$bind=null){return $this->db->query($sql,$bind);}
    public function fetchAll($sql,$bind=null){return $this->db->query($sql,$bind);}
    /********************** 链式处理 *************************/
    // 数据表切换
    public function table($tb,$opt=null)
    {
        $this->tableLink = $tb;
        if($opt) return $this->tableLink;
        return $this;
    }
    // 查询条件
    public function where($where,$opt=null)
    {
        //$this->whereLink = $this->db->parseWhere($where);
        $this->whereLink = $where;
        if($opt) return $this->whereLink;
        return $this;
    }
    // 筛选字段
    public function field($param,$opt=null)
    {
        $this->fieldLink = $this->db->feild($param);
        if($opt) return $this->fieldLink;
        return $this;
    }
    // 分页支持
    public function page($page=1,$num=null,$opt=null)
    {
        if(!is_numeric($page)){
            $arr = explode(',',$page);
            $page = is_numeric($arr[0])? $arr[0]:1;
            $num = isset($arr[1]) && is_numeric($arr[1])? $arr[1]:null;
        }
        if(empty($num)) $num = 30;
        $this->pageLink = [
            'page'=>$page,'num'=>$num
        ];
        if($opt) return $this->pageLink;
        return $this;
    }
    // 排序
    public function order($param)
    {
        $this->orderLink = '';
        if(is_string($param) && $param){
            $this->orderLink = 'order by '.$param;
        }
        return $this;
    }
    // 分组
    public function group($param)
    {
        $this->groupLink = '';
        if(is_string($param) && $param){
            $this->groupLink = 'group by '.$param;
        }
        return $this;
    }
    // 伪链式分页器-只有在page使用以后有效
    public function pageBar($ignore=false)
    {
        if($ignore) $this->pageBarLink = false;
        $this->pageBarLink = true;
        return $this;
    }
    // 伪链式等待处理数据
    public function data($data=null)
    {
        $this->dataLink = '';
        if(is_array($data)) $this->dataLink = $data;
        return $this;
    }
    // 伪链式SQL创建工具
    public function build($ignore=false)
    {
        $this->buildLink = null;
        if(!$ignore) $this->buildLink = true;
        return $this;
    }    
    // 设置数据库连接参数
    public function database($opt)
    {
        if(is_array($opt)) $this->dbOpt = $opt;
    }   
}